#include "CDynamicObject.h"
#include "irrString.h"
#include "irrThread.h"
namespace game
{
	namespace scene
	{
		CDynamicObject::CDynamicObject(	SDynamicObjectEntry* entry, 
										irr::scene::ISceneManager* sceneManager, 
										video::IVideoHandler* videoHandler) 
			:	IDynamicObject(entry, sceneManager, videoHandler)
		{
		}

		CDynamicObject::~CDynamicObject()
		{
			if(!this->Animations.empty())
			{
				irr::core::map<irr::core::stringc, SAnimationEntry*>::Iterator it = this->Animations.getIterator();
				it.reset(false);

				for(s32 i = this->Animations.size(); i > 0; i--)
				{
					SAnimationEntry* node = it.getNode()->getValue();

					delete node;

					it--;
				}
			}

			if(!this->Meshes.empty())
			{
				irr::core::map<irr::core::stringc, irr::scene::IAnimatedMesh*>::Iterator it = this->Meshes.getIterator();

				it.reset(false);

				for(s32 i = this->Meshes.size(); i>0; i--)
				{
					irr::scene::IAnimatedMesh* mesh = it.getNode()->getValue();

					mesh->drop();

					it--;
				}
			}

			if(!this->SceneNodes.empty())
			{
				irr::core::map<irr::core::stringc, irr::scene::IAnimatedMeshSceneNode*>::Iterator it = this->SceneNodes.getIterator();

				it.reset(false);

				for(s32 i = this->Meshes.size(); i>0; i--)
				{
					irr::scene::IAnimatedMeshSceneNode* meshSNode = it.getNode()->getValue();

					meshSNode->drop();

					it--;
				}	

			}

		}


		SAnimationEntry* CDynamicObject::getAnimationInfo(const c8* name)
		{
			SAnimationEntry* result = NULL;

			irr::core::stringc nameStr = name;

			if(this->Animations.find(nameStr) != NULL)
			{
				result = this->Animations[nameStr];
			}

			return result;
		}

		void CDynamicObject::addAnimationInfo(const c8* name, SAnimationEntry* animation)
		{
			irr::core::stringc nameStr = name;

			this->Animations.insert(nameStr, animation);
		}



		//! Adds named mesh to scene object
		void CDynamicObject::addMesh(const c8* name, irr::scene::IAnimatedMesh* mesh)
		{
			irr::core::stringc nameStr = name;
			nameStr.make_upper();

			this->Meshes.insert(nameStr, mesh);
			mesh->grab();

		}

		void CDynamicObject::addMesh(const c8* name, const c8* file)
		{
			irr::scene::IAnimatedMesh* mesh = this->SceneManager->getMesh(file);
			
			if(mesh)
			{
				this->addMesh(name, mesh);
				mesh->drop();
			}
		}


		void  CDynamicObject::addTexture(const c8* name, irr::video::ITexture* texture)
		{
			irr::core::stringc nameStr = name;
			nameStr.make_upper();

			this->Textures.insert(nameStr, texture);
			texture->grab();
		}

		void  CDynamicObject::addTexture(const c8* name, const c8* file)
		{
			irr::video::ITexture* texture = this->VideoHandler->getTexture(file);
			
			if(texture)
			{
				this->addTexture(name, texture);
			}
		}

		//! Adds object to game scene 
		void CDynamicObject::addToScene()
		{     
			
			irr::core::map<irr::core::stringc, irr::scene::IAnimatedMesh*>::Iterator it = this->Meshes.getIterator();
			it.reset(false);

			for(s32 i = this->Meshes.size(); i>0; i--)
			{
				irr::core::stringc meshName = it.getNode()->getKey();

				//enter critical section
				IDeviceManager::lockVideo();
				
				irr::scene::IAnimatedMeshSceneNode* sNode = this->SceneManager->addAnimatedMeshSceneNode(this->Meshes[meshName], this->Root);
				sNode->setMaterialFlag(irr::video::EMF_LIGHTING, false);
				sNode->setMaterialTexture(0, this->Textures[meshName]);
				
				//exit critical section
				IDeviceManager::unlockVideo();

				this->SceneNodes.insert(meshName, sNode);

				it--;
			}


		}

		


		void CDynamicObject::setScale(const irr::core::vector3df& value)
		{
			if(this->Root)
			{
				this->Root->setScale(value);
			}
		}

		irr::core::vector3df CDynamicObject::getScale()
		{
			irr::core::vector3df result = irr::core::vector3df(0,0,0);

			if(this->Root)
			{
				result = this->Root->getScale();
			}
			
			return result;
		}


		void CDynamicObject::setRotation(const irr::core::vector3df& value)
		{
			if(this->Root)
			{
				this->Root->setRotation(value);
			}
		}

		irr::core::vector3df CDynamicObject::getRotation()
		{
			irr::core::vector3df result = irr::core::vector3df(0,0,0);

			if(this->Root)
			{
				result = this->Root->getRotation();
			}
			
			return result;
		}

		EGAME_OBJECT_TYPE CDynamicObject::getType()
		{
			return this->Type; 
		}
	}
}